
#ifndef __MEM_STRUCT_H__
#define __MEM_STRUCT_H__

/** @file
 * Das Modul mem_struct stellt funktionen zum verwalten eines Speicherbereiches
 * bereit. Es wird First-Fit mittels einer nach Adressen sortierten Liste
 * implementiert. Zusätzlich wird freigegebener Speicher automatisch defragmentiert.
 * Ein Speicherblock wird immer auf ein vielfaches von 8 aufgerundet, um Platz für die Verwaltungsstruktur
 * zu gewährleisten und allozierte Speicherbereiche autmoatisch aligned zu halten.
 */

/**
 * Speicherbereiche werden intern als Listenelemente verwendet
 * mit jeweiliger Größe und dem Nachfolgerknoten.
 */
typedef struct mem_node {
    unsigned long size; ///< Größe
    struct mem_node *next; ///< Nachfolger
} mem_node_t;

/**
 * Speicherverwaltungsstruktur. Einfach verkettete Liste
 * von fragmentierten Speicherblöcken
 */
typedef struct mem_struct_t {
    mem_node_t *list;
} mem_struct_t;

/**
 * Initialisiert Verwaltungsstruktur eines Speicherbereichs mit 
 * Startadresse und Länge
 *
 * @param ms : Speicherverwaltungsstruktur
 * @param start : Startadesse. Muss aligned (ein vielfaches von 4) sein.
 * @param size : Größe des zu verwaltenden Speicherstückes
 *
 * @return Zeiger auf gegebene Speicherverwaltungsstruktur
 */
mem_struct_t *mem_init( mem_struct_t *ms, void* start, unsigned long size);

/**
 * Alloziert Speicher innerhalb des gegebenen verwalteten Speichers.
 *
 * @param ms : Speicherverwaltungsstruktur
 * @param size : Größe des zu allozierenden Speicherblocks
 *
 * @return Zeiger auf Speicherblock oder NULL, wenn nicht genügend Speicher 
 *         verfügbar ist.
 */
void *mem_alloc( mem_struct_t *ms, unsigned long size );

/**
 * Gibt allozierten Speicher wieder frei (und defragmentiert verwalteten
 * Speicher automatisch). 
 *
 * @param ms : Speicherverwaltungsstruktur
 * @param ptr : Freizugebendes Speicherstück
 * @param size : Größe des freizugebenden Speicherblockes
 */
void mem_free( mem_struct_t *ms, void* ptr, unsigned long size);

#endif

